// Viboard header file
// UI layer of ETB

#ifndef ETB_VIBOARD_H_
#define ETB_VIBOARD_H_

#include <string>
#include <vector>
#include <map>
#include <QImage>
#include <QString>
#include <QDomNode>
#include <QtGui/QMainWindow>
#include "EventBus.h"
#include "Config.h"

namespace etb {

//    class LcdDialog;
    class FakeJtag;

    // Viboard
    // UI layer of ETB
    class Viboard : public QMainWindow, public EventClient 
    {
      Q_OBJECT

    // constructors and destructors
    public:
      Viboard(EventBus* bus, QWidget *parent = 0, Qt::WindowFlags flags = 0);
      virtual ~Viboard();

    // public api
    public:
      void        init();
      void        setJtag(FakeJtag* jtag) { jtag_ = jtag; }
      U64         hexStrToAddr(const std::string str);
      QString     makeFilePath(QString p1, QString p2);

    // inherited public api
    public:
      void handleEvent(const std::string event);

    // inherited protected api
    protected:
      virtual void closeEvent(QCloseEvent *event);
      virtual void paintEvent(QPaintEvent *event);
      virtual void mouseMoveEvent(QMouseEvent *event);
      virtual void mousePressEvent(QMouseEvent *event);
      virtual void mouseReleaseEvent(QMouseEvent *event);
      virtual void mouseDoubleClickEvent(QMouseEvent *event);

    // slots
    public slots:
      void updateLcd();
      void updateStatusBar();

    // private members
    private:
      EventBus              *bus_;
      FakeJtag              *jtag_;
      QTimer                *timer_;
      U8                    *lcdAddr_;
      bool                  running_;

    private:
      class HotArea 
      {
      friend class Viboard;

      public:
        HotArea(QString name, QString status);
        ~HotArea();

      public:
        bool handleEvent(QString event);
        bool handleAction(QString action);
        void setHover(bool hovered);

      public:
        typedef struct {
          QString event;
          QString status;
        } HotAreaEvent;

        typedef struct {
          QString status;
          QString genEvent;
        } HotAreaToggle;

        typedef struct {
          QString action;
          QString status;
          QString genEvent;
        } HotAreaAction;

        typedef struct {
          int x;
          int y;
          int w;
          int h;
        } HotAreaRegion;

      private:
        void addEvent(QString event, QString status);
        void addToggleEvent(QString status, QString genEvent);
        void addAction(QString action, QString status, QString genEvent);
        void getEventResult(QString event, QString& status);
        void getActionResult(QString action, QString& status, QString& genEvent);
        void getToggleResult(QString& status, QString& genEvent);
          
      private:
        std::vector<HotAreaEvent*>  events_;
        std::vector<HotAreaAction*> actions_;
        std::vector<HotAreaToggle*> toggles_;

        QString       name_;
        HotAreaRegion region_;
        QString       status_;
        bool          hovered_;
        bool          focusable_;
        QString       tips_;
        bool          togglable_;
      };

    private:
      HotArea*  findAreaByName(QString name);
      HotArea*  findAreaByPos(int x, int y);
      void      redrawArea(HotArea* area);
      void      parseXmlStates(QDomNode& n);
      void      parseXmlDevice(QDomNode& n);
      void      parseXmlDeviceToggle(QDomNode& node, HotArea* ha);
      bool      isOutBoundArea(int x, int y, HotArea *ha);
      void      sendEvent(QString deviceName, QString event);
      void      clearAllAreaStatus();

      // for debug purpose
      void      dumpAreas();

    private:
      HotArea               *lastHovered_;
      QString               defaultStatus_;
      QImage                bufferImg_;
      std::vector<HotArea*> areas_;

      // status name, image;
      std::map<QString, QImage> status_;
    };
}

#endif  // ETB_VIBOARD_H_
